#include <stdlib.h>
#include <pthread.h>

#ifndef STACK_H
#define STACK_H

struct stackelem
{
  int *data;
  struct stackelem *next;
};

typedef struct stackelem stackelem_t;

stackelem_t *stackelem_alloc();
int stackelem_init(stackelem_t *);
int stackelem_free(stackelem_t *);
int stackelem_write(stackelem_t *, int);
int stackelem_read(stackelem_t *);

struct stack
{
  stackelem_t *top;
  pthread_mutex_t *lock;
};

typedef struct stack stack_t;

stack_t *stack_alloc();
int stack_init(stack_t *);
int stack_free(stack_t *);
int stack_isempty(stack_t *);
int stack_peek(stack_t *);

int stack_push_elem(stack_t *, stackelem_t *);
int stack_pop_elem(stack_t *, stackelem_t **);

int stack_push_elem_safe(stack_t *, stackelem_t *);
int stack_pop_elem_safe(stack_t *, stackelem_t **);

int stack_init_treiber(stack_t *);
int stack_push_treiber(stack_t *, stackelem_t *);
int stack_pop_treiber(stack_t *, stackelem_t **);
int stack_pop_treiber_aba(stack_t *, stackelem_t **, int);

void print_stack(stackelem_t *, int);

#endif /* STACK_H */
